/**
  ******************************************************************************
  * @file    stm32f4xx_hal_rcc_ex.c
  * @author  MCD Application Team
  * @brief   Extension RCC HAL module driver.
  *          This file provides firmware functions to manage the following
  *          functionalities RCC extension peripheral:
  *           + Extended Peripheral Control functions
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"

/** @addtogroup STM32F4xx_HAL_Driver
  * @{
  */

/** @defgroup RCCEx RCCEx
  * @brief RCCEx HAL module driver
  * @{
  */

#ifdef HAL_RCC_MODULE_ENABLED

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @addtogroup RCCEx_Private_Constants
  * @{
  */
/**
  * @}
  */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
  *  @{
  */

/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
 *  @brief  Extended Peripheral Control functions
 *
@verbatim
 ===============================================================================
                ##### Extended Peripheral Control functions  #####
 ===============================================================================
    [..]
    This subsection provides a set of functions allowing to control the RCC Clocks
    frequencies.
    [..]
    (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
        select the RTC clock source; in this case the Backup domain will be reset in
        order to modify the RTC Clock source, as consequence RTC registers (including
        the backup registers) and RCC_BDCR register are set to their reset values.

@endverbatim
  * @{
  */

#if defined(STM32F446xx)
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals
  *         clocks(I2S, SAI, LTDC RTC and TIM).
  *
  * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
  *         the RTC clock source; in this case the Backup domain will be reset in
  *         order to modify the RTC Clock source, as consequence RTC registers (including
  *         the backup registers) and RCC_BDCR register are set to their reset values.
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0U;
    uint32_t tmpreg1 = 0U;
    uint32_t plli2sp = 0U;
    uint32_t plli2sq = 0U;
    uint32_t plli2sr = 0U;
    uint32_t pllsaip = 0U;
    uint32_t pllsaiq = 0U;
    uint32_t plli2sused = 0U;
    uint32_t pllsaiused = 0U;

    /* Check the peripheral clock selection parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*------------------------ I2S APB1 configuration --------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == (RCC_PERIPHCLK_I2S_APB1))
    {
        /* Check the parameters */
        assert_param(IS_RCC_I2SAPB1CLKSOURCE(PeriphClkInit->I2sApb1ClockSelection));

        /* Configure I2S Clock source */
        __HAL_RCC_I2S_APB1_CONFIG(PeriphClkInit->I2sApb1ClockSelection);
        /* Enable the PLLI2S when it's used as clock source for I2S */
        if(PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)
        {
            plli2sused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- I2S APB2 configuration ----------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == (RCC_PERIPHCLK_I2S_APB2))
    {
        /* Check the parameters */
        assert_param(IS_RCC_I2SAPB2CLKSOURCE(PeriphClkInit->I2sApb2ClockSelection));

        /* Configure I2S Clock source */
        __HAL_RCC_I2S_APB2_CONFIG(PeriphClkInit->I2sApb2ClockSelection);
        /* Enable the PLLI2S when it's used as clock source for I2S */
        if(PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)
        {
            plli2sused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*--------------------------- SAI1 configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == (RCC_PERIPHCLK_SAI1))
    {
        /* Check the parameters */
        assert_param(IS_RCC_SAI1CLKSOURCE(PeriphClkInit->Sai1ClockSelection));

        /* Configure SAI1 Clock source */
        __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
        /* Enable the PLLI2S when it's used as clock source for SAI */
        if(PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)
        {
            plli2sused = 1U;
        }
        /* Enable the PLLSAI when it's used as clock source for SAI */
        if(PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)
        {
            pllsaiused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*-------------------------- SAI2 configuration ----------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == (RCC_PERIPHCLK_SAI2))
    {
        /* Check the parameters */
        assert_param(IS_RCC_SAI2CLKSOURCE(PeriphClkInit->Sai2ClockSelection));

        /* Configure SAI2 Clock source */
        __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection);

        /* Enable the PLLI2S when it's used as clock source for SAI */
        if(PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S)
        {
            plli2sused = 1U;
        }
        /* Enable the PLLSAI when it's used as clock source for SAI */
        if(PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI)
        {
            pllsaiused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------------- RTC configuration --------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
    {
        /* Check for RTC Parameters used to output RTCCLK */
        assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        PWR->CR |= PWR_CR_DBP;

        /* Get tick */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }
        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
        if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
        {
            /* Store the content of BDCR register before the reset of Backup Domain */
            tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();
            /* Restore the Content of BDCR register */
            RCC->BDCR = tmpreg1;

            /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
            if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
            {
                /* Get tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- TIM configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
    {
        /* Configure Timer Prescaler */
        __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- FMPI2C1 Configuration -----------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1)
    {
        /* Check the parameters */
        assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection));

        /* Configure the FMPI2C1 clock source */
        __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------ CEC Configuration -------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CEC) == RCC_PERIPHCLK_CEC)
    {
        /* Check the parameters */
        assert_param(IS_RCC_CECCLKSOURCE(PeriphClkInit->CecClockSelection));

        /* Configure the CEC clock source */
        __HAL_RCC_CEC_CONFIG(PeriphClkInit->CecClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------------- CLK48 Configuration ------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
    {
        /* Check the parameters */
        assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection));

        /* Configure the CLK48 clock source */
        __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);

        /* Enable the PLLSAI when it's used as clock source for CLK48 */
        if(PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP)
        {
            pllsaiused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------------- SDIO Configuration -------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO)
    {
        /* Check the parameters */
        assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection));

        /* Configure the SDIO clock source */
        __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------ SPDIFRX Configuration ---------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX)
    {
        /* Check the parameters */
        assert_param(IS_RCC_SPDIFRXCLKSOURCE(PeriphClkInit->SpdifClockSelection));

        /* Configure the SPDIFRX clock source */
        __HAL_RCC_SPDIFRX_CONFIG(PeriphClkInit->SpdifClockSelection);
        /* Enable the PLLI2S when it's used as clock source for SPDIFRX */
        if(PeriphClkInit->SpdifClockSelection == RCC_SPDIFRXCLKSOURCE_PLLI2SP)
        {
            plli2sused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- PLLI2S Configuration ------------------------*/
    /* PLLI2S is configured when a peripheral will use it as source clock : SAI1, SAI2, I2S on APB1,
       I2S on APB2 or SPDIFRX */
    if((plli2sused == 1U) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
    {
        /* Disable the PLLI2S */
        __HAL_RCC_PLLI2S_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /* check for common PLLI2S Parameters */
        assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM));
        assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));

        /*------ In Case of PLLI2S is selected as source clock for I2S -----------*/
        if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == RCC_PERIPHCLK_I2S_APB1) && (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == RCC_PERIPHCLK_I2S_APB2) && (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)))
        {
            /* check for Parameters */
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));

            /* Read PLLI2SP/PLLI2SQ value from PLLI2SCFGR register (this value is not needed for I2S configuration) */
            plli2sp = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
            plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
            /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sp, plli2sq, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /*------- In Case of PLLI2S is selected as source clock for SAI ----------*/
        if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S)))
        {
            /* Check for PLLI2S Parameters */
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
            /* Check for PLLI2S/DIVQ parameters */
            assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));

            /* Read PLLI2SP/PLLI2SR value from PLLI2SCFGR register (this value is not needed for SAI configuration) */
            plli2sp = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
            plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sp, PeriphClkInit->PLLI2S.PLLI2SQ, plli2sr);

            /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
            __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
        }

        /*------ In Case of PLLI2S is selected as source clock for SPDIFRX -------*/
        if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX) && (PeriphClkInit->SpdifClockSelection == RCC_SPDIFRXCLKSOURCE_PLLI2SP))
        {
            /* check for Parameters */
            assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP));
            /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */
            plli2sq = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
            plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
            /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SP, plli2sq, plli2sr);
        }

        /*----------------- In Case of PLLI2S is just selected  -----------------*/
        if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
        {
            /* Check for Parameters */
            assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP));
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));

            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SP, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /* Enable the PLLI2S */
        __HAL_RCC_PLLI2S_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------------- PLLSAI Configuration -----------------------*/
    /* PLLSAI is configured when a peripheral will use it as source clock : SAI1, SAI2, CLK48 or SDIO */
    if(pllsaiused == 1U)
    {
        /* Disable PLLSAI Clock */
        __HAL_RCC_PLLSAI_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLSAI is disabled */
        while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /* Check the PLLSAI division factors */
        assert_param(IS_RCC_PLLSAIM_VALUE(PeriphClkInit->PLLSAI.PLLSAIM));
        assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));

        /*------ In Case of PLLSAI is selected as source clock for SAI -----------*/
        if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI)))
        {
            /* check for PLLSAIQ Parameter */
            assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
            /* check for PLLSAI/DIVQ Parameter */
            assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));

            /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
            pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIM, PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, PeriphClkInit->PLLSAI.PLLSAIQ, 0U);

            /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
            __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
        }

        /*------ In Case of PLLSAI is selected as source clock for CLK48 ---------*/
        /* In Case of PLLI2S is selected as source clock for CLK48 */
        if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP))
        {
            /* check for Parameters */
            assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP));
            /* Read PLLSAIQ value from PLLI2SCFGR register (this value is not need for SAI configuration) */
            pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
            /* Configure the PLLSAI division factors */
            /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * (PLLI2SN/PLLSAIM) */
            /* 48CLK = f(PLLSAI clock output) = f(VCO clock) / PLLSAIP */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIM, PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIP, pllsaiq, 0U);
        }

        /* Enable PLLSAI Clock */
        __HAL_RCC_PLLSAI_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLSAI is ready */
        while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }
    return HAL_OK;
}

/**
  * @brief  Get the RCC_PeriphCLKInitTypeDef according to the internal
  *         RCC configuration registers.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         will be configured.
  * @retval None
  */
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tempreg;

    /* Set all possible values for the extended clock type parameter------------*/
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 | \
                                          RCC_PERIPHCLK_SAI1     | RCC_PERIPHCLK_SAI2     | \
                                          RCC_PERIPHCLK_TIM      | RCC_PERIPHCLK_RTC      | \
                                          RCC_PERIPHCLK_CEC      | RCC_PERIPHCLK_FMPI2C1  | \
                                          RCC_PERIPHCLK_CLK48     | RCC_PERIPHCLK_SDIO     | \
                                          RCC_PERIPHCLK_SPDIFRX;

    /* Get the PLLI2S Clock configuration --------------------------------------*/
    PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM) >> RCC_PLLI2SCFGR_PLLI2SM_Pos);
    PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
    PeriphClkInit->PLLI2S.PLLI2SP = (uint32_t)((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
    PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
    PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
    /* Get the PLLSAI Clock configuration --------------------------------------*/
    PeriphClkInit->PLLSAI.PLLSAIM = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM) >> RCC_PLLSAICFGR_PLLSAIM_Pos);
    PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos);
    PeriphClkInit->PLLSAI.PLLSAIP = (uint32_t)((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
    PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
    /* Get the PLLSAI/PLLI2S division factors ----------------------------------*/
    PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos);
    PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos);

    /* Get the SAI1 clock configuration ----------------------------------------*/
    PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();

    /* Get the SAI2 clock configuration ----------------------------------------*/
    PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE();

    /* Get the I2S APB1 clock configuration ------------------------------------*/
    PeriphClkInit->I2sApb1ClockSelection = __HAL_RCC_GET_I2S_APB1_SOURCE();

    /* Get the I2S APB2 clock configuration ------------------------------------*/
    PeriphClkInit->I2sApb2ClockSelection = __HAL_RCC_GET_I2S_APB2_SOURCE();

    /* Get the RTC Clock configuration -----------------------------------------*/
    tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
    PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));

    /* Get the CEC clock configuration -----------------------------------------*/
    PeriphClkInit->CecClockSelection = __HAL_RCC_GET_CEC_SOURCE();

    /* Get the FMPI2C1 clock configuration -------------------------------------*/
    PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE();

    /* Get the CLK48 clock configuration ----------------------------------------*/
    PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();

    /* Get the SDIO clock configuration ----------------------------------------*/
    PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE();

    /* Get the SPDIFRX clock configuration -------------------------------------*/
    PeriphClkInit->SpdifClockSelection = __HAL_RCC_GET_SPDIFRX_SOURCE();

    /* Get the TIM Prescaler configuration -------------------------------------*/
    if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
    }
    else
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
    }
}

/**
  * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
  * @note   Return 0 if peripheral clock identifier not managed by this API
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg RCC_PERIPHCLK_SAI1: SAI1 peripheral clock
  *            @arg RCC_PERIPHCLK_SAI2: SAI2 peripheral clock
  *            @arg RCC_PERIPHCLK_I2S_APB1: I2S APB1 peripheral clock
  *            @arg RCC_PERIPHCLK_I2S_APB2: I2S APB2 peripheral clock
  * @retval Frequency in KHz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    uint32_t tmpreg1 = 0U;
    /* This variable used to store the SAI clock frequency (value in Hz) */
    uint32_t frequency = 0U;
    /* This variable used to store the VCO Input (value in Hz) */
    uint32_t vcoinput = 0U;
    /* This variable used to store the SAI clock source */
    uint32_t saiclocksource = 0U;
    uint32_t srcclk = 0U;
    /* This variable used to store the VCO Output (value in Hz) */
    uint32_t vcooutput = 0U;
    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_SAI1:
    case RCC_PERIPHCLK_SAI2:
    {
        saiclocksource = RCC->DCKCFGR;
        saiclocksource &= (RCC_DCKCFGR_SAI1SRC | RCC_DCKCFGR_SAI2SRC);
        switch (saiclocksource)
        {
        case 0U: /* PLLSAI is the clock source for SAI*/
        {
            /* Configure the PLLSAI division factor */
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLSAIM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
            {
                /* In Case the PLL Source is HSI (Internal Clock) */
                vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM));
            }
            else
            {
                /* In Case the PLL Source is HSE (External Clock) */
                vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM)));
            }
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
            tmpreg1 = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24U;
            frequency = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6U)) / (tmpreg1);

            /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
            tmpreg1 = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> 8U) + 1U);
            frequency = frequency / (tmpreg1);
            break;
        }
        case RCC_DCKCFGR_SAI1SRC_0: /* PLLI2S is the clock source for SAI*/
        case RCC_DCKCFGR_SAI2SRC_0: /* PLLI2S is the clock source for SAI*/
        {
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
            {
                /* In Case the PLL Source is HSI (Internal Clock) */
                vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
            else
            {
                /* In Case the PLL Source is HSE (External Clock) */
                vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)));
            }

            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
            tmpreg1 = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24U;
            frequency = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U)) / (tmpreg1);

            /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
            tmpreg1 = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) + 1U);
            frequency = frequency / (tmpreg1);
            break;
        }
        case RCC_DCKCFGR_SAI1SRC_1: /* PLLR is the clock source for SAI*/
        case RCC_DCKCFGR_SAI2SRC_1: /* PLLR is the clock source for SAI*/
        {
            /* Configure the PLLI2S division factor */
            /* PLL_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
            {
                /* In Case the PLL Source is HSI (Internal Clock) */
                vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* In Case the PLL Source is HSE (External Clock) */
                vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)));
            }

            /* PLL_VCO Output = PLL_VCO Input * PLLN */
            /* SAI_CLK_x = PLL_VCO Output/PLLR */
            tmpreg1 = (RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U;
            frequency = (vcoinput * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U)) / (tmpreg1);
            break;
        }
        case RCC_DCKCFGR_SAI1SRC: /* External clock is the clock source for SAI*/
        {
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        case RCC_DCKCFGR_SAI2SRC: /* PLLSRC(HSE or HSI) is the clock source for SAI*/
        {
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
            {
                /* In Case the PLL Source is HSI (Internal Clock) */
                frequency = (uint32_t)(HSI_VALUE);
            }
            else
            {
                /* In Case the PLL Source is HSE (External Clock) */
                frequency = (uint32_t)(HSE_VALUE);
            }
            break;
        }
        default :
        {
            break;
        }
        }
        break;
    }
    case RCC_PERIPHCLK_I2S_APB1:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_APB1_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SAPB1CLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SAPB1CLKSOURCE_PLLI2S:
        {
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }

            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
        case RCC_I2SAPB1CLKSOURCE_PLLR:
        {
            /* Configure the PLL division factor R */
            /* PLL_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLL_VCO Output = PLL_VCO Input * PLLN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
            /* I2S_CLK = PLL_VCO Output/PLLR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
        case RCC_I2SAPB1CLKSOURCE_PLLSRC:
        {
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                frequency = HSE_VALUE;
            }
            else
            {
                frequency = HSI_VALUE;
            }
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    case RCC_PERIPHCLK_I2S_APB2:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_APB2_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SAPB2CLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SAPB2CLKSOURCE_PLLI2S:
        {
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }

            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
        case RCC_I2SAPB2CLKSOURCE_PLLR:
        {
            /* Configure the PLL division factor R */
            /* PLL_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLL_VCO Output = PLL_VCO Input * PLLN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
            /* I2S_CLK = PLL_VCO Output/PLLR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
        case RCC_I2SAPB2CLKSOURCE_PLLSRC:
        {
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                frequency = HSE_VALUE;
            }
            else
            {
                frequency = HSI_VALUE;
            }
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    }
    return frequency;
}
#endif /* STM32F446xx */

#if defined(STM32F469xx) || defined(STM32F479xx)
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals
  *         clocks(I2S, SAI, LTDC, RTC and TIM).
  *
  * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
  *         the RTC clock source; in this case the Backup domain will be reset in
  *         order to modify the RTC Clock source, as consequence RTC registers (including
  *         the backup registers) and RCC_BDCR register are set to their reset values.
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0U;
    uint32_t tmpreg1 = 0U;
    uint32_t pllsaip = 0U;
    uint32_t pllsaiq = 0U;
    uint32_t pllsair = 0U;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*--------------------------- CLK48 Configuration --------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
    {
        /* Check the parameters */
        assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection));

        /* Configure the CLK48 clock source */
        __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------ SDIO Configuration ------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO)
    {
        /* Check the parameters */
        assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection));

        /* Configure the SDIO clock source */
        __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------- SAI/I2S Configuration (PLLI2S) -------------------*/
    /*------------------- Common configuration SAI/I2S -------------------------*/
    /* In Case of SAI or I2S Clock Configuration through PLLI2S, PLLI2SN division
       factor is common parameters for both peripherals */
    if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == RCC_PERIPHCLK_SAI_PLLI2S) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S))
    {
        /* check for Parameters */
        assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));

        /* Disable the PLLI2S */
        __HAL_RCC_PLLI2S_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /*---------------------- I2S configuration -------------------------------*/
        /* In Case of I2S Clock Configuration through PLLI2S, PLLI2SR must be added
          only for I2S configuration */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))
        {
            /* check for Parameters */
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x (PLLI2SN/PLLM) */
            /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /*---------------------------- SAI configuration -------------------------*/
        /* In Case of SAI Clock Configuration through PLLI2S, PLLI2SQ and PLLI2S_DIVQ must
           be added only for SAI configuration */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == (RCC_PERIPHCLK_SAI_PLLI2S))
        {
            /* Check the PLLI2S division factors */
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
            assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));

            /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */
            tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
            __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, tmpreg1);
            /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
            __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
        }

        /*----------------- In Case of PLLI2S is just selected  -----------------*/
        if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
        {
            /* Check for Parameters */
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));

            /* Configure the PLLI2S multiplication and division factors */
            __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /* Enable the PLLI2S */
        __HAL_RCC_PLLI2S_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------- SAI/LTDC Configuration (PLLSAI) ------------------*/
    /*----------------------- Common configuration SAI/LTDC --------------------*/
    /* In Case of SAI, LTDC or CLK48 Clock Configuration through PLLSAI, PLLSAIN division
       factor is common parameters for these peripherals */
    if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == RCC_PERIPHCLK_SAI_PLLSAI) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)             ||
            ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)          &&
             (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP)))
    {
        /* Check the PLLSAI division factors */
        assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));

        /* Disable PLLSAI Clock */
        __HAL_RCC_PLLSAI_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLSAI is disabled */
        while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /*---------------------------- SAI configuration -------------------------*/
        /* In Case of SAI Clock Configuration through PLLSAI, PLLSAIQ and PLLSAI_DIVQ must
           be added only for SAI configuration */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == (RCC_PERIPHCLK_SAI_PLLSAI))
        {
            assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
            assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));

            /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
            pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
            /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
            pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, PeriphClkInit->PLLSAI.PLLSAIQ, pllsair);
            /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
            __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
        }

        /*---------------------------- LTDC configuration ------------------------*/
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC))
        {
            assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR));
            assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR));

            /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
            pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
            /* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */
            pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, pllsaiq, PeriphClkInit->PLLSAI.PLLSAIR);
            /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */
            __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR);
        }

        /*---------------------------- CLK48 configuration ------------------------*/
        /* Configure the PLLSAI when it is used as clock source for CLK48 */
        if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == (RCC_PERIPHCLK_CLK48)) &&
                (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP))
        {
            assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP));

            /* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */
            pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
            /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
            pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* CLK48_CLK(first level) = PLLSAI_VCO Output/PLLSAIP */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIP, pllsaiq, pllsair);
        }

        /* Enable PLLSAI Clock */
        __HAL_RCC_PLLSAI_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLSAI is ready */
        while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }

    /*--------------------------------------------------------------------------*/

    /*---------------------------- RTC configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
    {
        /* Check for RTC Parameters used to output RTCCLK */
        assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        PWR->CR |= PWR_CR_DBP;

        /* Get tick */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }
        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
        if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
        {
            /* Store the content of BDCR register before the reset of Backup Domain */
            tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();
            /* Restore the Content of BDCR register */
            RCC->BDCR = tmpreg1;

            /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
            if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
            {
                /* Get tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- TIM configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
    {
        __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
    }
    return HAL_OK;
}

/**
  * @brief  Configures the RCC_PeriphCLKInitTypeDef according to the internal
  * RCC configuration registers.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         will be configured.
  * @retval None
  */
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tempreg;

    /* Set all possible values for the extended clock type parameter------------*/
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S        | RCC_PERIPHCLK_SAI_PLLSAI | \
                                          RCC_PERIPHCLK_SAI_PLLI2S | RCC_PERIPHCLK_LTDC       | \
                                          RCC_PERIPHCLK_TIM        | RCC_PERIPHCLK_RTC        | \
                                          RCC_PERIPHCLK_CLK48       | RCC_PERIPHCLK_SDIO;

    /* Get the PLLI2S Clock configuration --------------------------------------*/
    PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
    PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
    PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
    /* Get the PLLSAI Clock configuration --------------------------------------*/
    PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos);
    PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
    PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
    /* Get the PLLSAI/PLLI2S division factors ----------------------------------*/
    PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos);
    PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos);
    PeriphClkInit->PLLSAIDivR = (uint32_t)(RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVR);
    /* Get the RTC Clock configuration -----------------------------------------*/
    tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
    PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));

    /* Get the CLK48 clock configuration -------------------------------------*/
    PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();

    /* Get the SDIO clock configuration ----------------------------------------*/
    PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE();

    if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
    }
    else
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
    }
}

/**
  * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
  * @note   Return 0 if peripheral clock identifier not managed by this API
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
  * @retval Frequency in KHz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    /* This variable used to store the I2S clock frequency (value in Hz) */
    uint32_t frequency = 0U;
    /* This variable used to store the VCO Input (value in Hz) */
    uint32_t vcoinput = 0U;
    uint32_t srcclk = 0U;
    /* This variable used to store the VCO Output (value in Hz) */
    uint32_t vcooutput = 0U;
    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_I2S:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SCLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SCLKSOURCE_PLLI2S:
        {
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    }
    return frequency;
}
#endif /* STM32F469xx || STM32F479xx */

#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals
  *         clocks(I2S, LTDC RTC and TIM).
  *
  * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
  *         the RTC clock source; in this case the Backup domain will be reset in
  *         order to modify the RTC Clock source, as consequence RTC registers (including
  *         the backup registers) and RCC_BDCR register are set to their reset values.
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0U;
    uint32_t tmpreg1 = 0U;
#if defined(STM32F413xx) || defined(STM32F423xx)
    uint32_t plli2sq = 0U;
#endif /* STM32F413xx || STM32F423xx */
    uint32_t plli2sused = 0U;

    /* Check the peripheral clock selection parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*----------------------------------- I2S APB1 configuration ---------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == (RCC_PERIPHCLK_I2S_APB1))
    {
        /* Check the parameters */
        assert_param(IS_RCC_I2SAPB1CLKSOURCE(PeriphClkInit->I2sApb1ClockSelection));

        /* Configure I2S Clock source */
        __HAL_RCC_I2S_APB1_CONFIG(PeriphClkInit->I2sApb1ClockSelection);
        /* Enable the PLLI2S when it's used as clock source for I2S */
        if(PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)
        {
            plli2sused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------------------- I2S APB2 configuration ---------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == (RCC_PERIPHCLK_I2S_APB2))
    {
        /* Check the parameters */
        assert_param(IS_RCC_I2SAPB2CLKSOURCE(PeriphClkInit->I2sApb2ClockSelection));

        /* Configure I2S Clock source */
        __HAL_RCC_I2S_APB2_CONFIG(PeriphClkInit->I2sApb2ClockSelection);
        /* Enable the PLLI2S when it's used as clock source for I2S */
        if(PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)
        {
            plli2sused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

#if defined(STM32F413xx) || defined(STM32F423xx)
    /*----------------------- SAI1 Block A configuration -----------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIA) == (RCC_PERIPHCLK_SAIA))
    {
        /* Check the parameters */
        assert_param(IS_RCC_SAIACLKSOURCE(PeriphClkInit->SaiAClockSelection));

        /* Configure SAI1 Clock source */
        __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(PeriphClkInit->SaiAClockSelection);
        /* Enable the PLLI2S when it's used as clock source for SAI */
        if(PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLI2SR)
        {
            plli2sused = 1U;
        }
        /* Enable the PLLSAI when it's used as clock source for SAI */
        if(PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLR)
        {
            /* Check for PLL/DIVR parameters */
            assert_param(IS_RCC_PLL_DIVR_VALUE(PeriphClkInit->PLLDivR));

            /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */
            __HAL_RCC_PLL_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLDivR);
        }
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------- SAI1 Block B configuration ------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIB) == (RCC_PERIPHCLK_SAIB))
    {
        /* Check the parameters */
        assert_param(IS_RCC_SAIBCLKSOURCE(PeriphClkInit->SaiBClockSelection));

        /* Configure SAI1 Clock source */
        __HAL_RCC_SAI_BLOCKBCLKSOURCE_CONFIG(PeriphClkInit->SaiBClockSelection);
        /* Enable the PLLI2S when it's used as clock source for SAI */
        if(PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLI2SR)
        {
            plli2sused = 1U;
        }
        /* Enable the PLLSAI when it's used as clock source for SAI */
        if(PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLR)
        {
            /* Check for PLL/DIVR parameters */
            assert_param(IS_RCC_PLL_DIVR_VALUE(PeriphClkInit->PLLDivR));

            /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */
            __HAL_RCC_PLL_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLDivR);
        }
    }
    /*--------------------------------------------------------------------------*/
#endif /* STM32F413xx || STM32F423xx */

    /*------------------------------------ RTC configuration -------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
    {
        /* Check for RTC Parameters used to output RTCCLK */
        assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        PWR->CR |= PWR_CR_DBP;

        /* Get tick */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }
        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
        if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
        {
            /* Store the content of BDCR register before the reset of Backup Domain */
            tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();
            /* Restore the Content of BDCR register */
            RCC->BDCR = tmpreg1;

            /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
            if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
            {
                /* Get tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------------ TIM configuration -------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
    {
        /* Configure Timer Prescaler */
        __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------------- FMPI2C1 Configuration --------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1)
    {
        /* Check the parameters */
        assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection));

        /* Configure the FMPI2C1 clock source */
        __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------------- CLK48 Configuration ----------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
    {
        /* Check the parameters */
        assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection));

        /* Configure the SDIO clock source */
        __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);

        /* Enable the PLLI2S when it's used as clock source for CLK48 */
        if(PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)
        {
            plli2sused = 1U;
        }
    }
    /*--------------------------------------------------------------------------*/

    /*------------------------------------- SDIO Configuration -----------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO)
    {
        /* Check the parameters */
        assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection));

        /* Configure the SDIO clock source */
        __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*-------------------------------------- PLLI2S Configuration --------------*/
    /* PLLI2S is configured when a peripheral will use it as source clock : I2S on APB1 or
       I2S on APB2*/
    if((plli2sused == 1U) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
    {
        /* Disable the PLLI2S */
        __HAL_RCC_PLLI2S_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /* check for common PLLI2S Parameters */
        assert_param(IS_RCC_PLLI2SCLKSOURCE(PeriphClkInit->PLLI2SSelection));
        assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM));
        assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
        /*-------------------- Set the PLL I2S clock -----------------------------*/
        __HAL_RCC_PLL_I2S_CONFIG(PeriphClkInit->PLLI2SSelection);

        /*------- In Case of PLLI2S is selected as source clock for I2S ----------*/
        if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == RCC_PERIPHCLK_I2S_APB1) && (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == RCC_PERIPHCLK_I2S_APB2) && (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO) && (PeriphClkInit->SdioClockSelection == RCC_SDIOCLKSOURCE_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)))
        {
            /* check for Parameters */
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));

            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/
            /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
        }

#if defined(STM32F413xx) || defined(STM32F423xx)
        /*------- In Case of PLLI2S is selected as source clock for SAI ----------*/
        if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIA) == RCC_PERIPHCLK_SAIA) && (PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLI2SR)) ||
                ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIB) == RCC_PERIPHCLK_SAIB) && (PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLI2SR)))
        {
            /* Check for PLLI2S Parameters */
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
            /* Check for PLLI2S/DIVR parameters */
            assert_param(IS_RCC_PLLI2S_DIVR_VALUE(PeriphClkInit->PLLI2SDivR));

            /* Read PLLI2SQ value from PLLI2SCFGR register (this value is not needed for SAI configuration) */
            plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sq, PeriphClkInit->PLLI2S.PLLI2SR);

            /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVR */
            __HAL_RCC_PLLI2S_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLI2SDivR);
        }
#endif /* STM32F413xx || STM32F423xx */

        /*----------------- In Case of PLLI2S is just selected  ------------------*/
        if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
        {
            /* Check for Parameters */
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));

            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/
            /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /* Enable the PLLI2S */
        __HAL_RCC_PLLI2S_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }
    /*--------------------------------------------------------------------------*/

    /*-------------------- DFSDM1 clock source configuration -------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1)
    {
        /* Check the parameters */
        assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection));

        /* Configure the DFSDM1 interface clock source */
        __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*-------------------- DFSDM1 Audio clock source configuration -------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1_AUDIO) == RCC_PERIPHCLK_DFSDM1_AUDIO)
    {
        /* Check the parameters */
        assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection));

        /* Configure the DFSDM1 Audio interface clock source */
        __HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection);
    }
    /*--------------------------------------------------------------------------*/

#if defined(STM32F413xx) || defined(STM32F423xx)
    /*-------------------- DFSDM2 clock source configuration -------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2) == RCC_PERIPHCLK_DFSDM2)
    {
        /* Check the parameters */
        assert_param(IS_RCC_DFSDM2CLKSOURCE(PeriphClkInit->Dfsdm2ClockSelection));

        /* Configure the DFSDM1 interface clock source */
        __HAL_RCC_DFSDM2_CONFIG(PeriphClkInit->Dfsdm2ClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*-------------------- DFSDM2 Audio clock source configuration -------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2_AUDIO) == RCC_PERIPHCLK_DFSDM2_AUDIO)
    {
        /* Check the parameters */
        assert_param(IS_RCC_DFSDM2AUDIOCLKSOURCE(PeriphClkInit->Dfsdm2AudioClockSelection));

        /* Configure the DFSDM1 Audio interface clock source */
        __HAL_RCC_DFSDM2AUDIO_CONFIG(PeriphClkInit->Dfsdm2AudioClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- LPTIM1 Configuration ------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1)
    {
        /* Check the parameters */
        assert_param(IS_RCC_LPTIM1CLKSOURCE(PeriphClkInit->Lptim1ClockSelection));

        /* Configure the LPTIM1 clock source */
        __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
    }
    /*--------------------------------------------------------------------------*/
#endif /* STM32F413xx || STM32F423xx */

    return HAL_OK;
}

/**
  * @brief  Get the RCC_PeriphCLKInitTypeDef according to the internal
  *         RCC configuration registers.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         will be configured.
  * @retval None
  */
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tempreg;

    /* Set all possible values for the extended clock type parameter------------*/
#if defined(STM32F413xx) || defined(STM32F423xx)
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1     | RCC_PERIPHCLK_I2S_APB2 | \
                                          RCC_PERIPHCLK_TIM          | RCC_PERIPHCLK_RTC      | \
                                          RCC_PERIPHCLK_FMPI2C1      | RCC_PERIPHCLK_CLK48    | \
                                          RCC_PERIPHCLK_SDIO         | RCC_PERIPHCLK_DFSDM1   | \
                                          RCC_PERIPHCLK_DFSDM1_AUDIO | RCC_PERIPHCLK_DFSDM2   | \
                                          RCC_PERIPHCLK_DFSDM2_AUDIO | RCC_PERIPHCLK_LPTIM1   | \
                                          RCC_PERIPHCLK_SAIA         | RCC_PERIPHCLK_SAIB;
#else /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 | \
                                          RCC_PERIPHCLK_TIM      | RCC_PERIPHCLK_RTC      | \
                                          RCC_PERIPHCLK_FMPI2C1  | RCC_PERIPHCLK_CLK48    | \
                                          RCC_PERIPHCLK_SDIO     | RCC_PERIPHCLK_DFSDM1   | \
                                          RCC_PERIPHCLK_DFSDM1_AUDIO;
#endif /* STM32F413xx || STM32F423xx */



    /* Get the PLLI2S Clock configuration --------------------------------------*/
    PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM) >> RCC_PLLI2SCFGR_PLLI2SM_Pos);
    PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
    PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
    PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
#if defined(STM32F413xx) || defined(STM32F423xx)
    /* Get the PLL/PLLI2S division factors -------------------------------------*/
    PeriphClkInit->PLLI2SDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVR) >> RCC_DCKCFGR_PLLI2SDIVR_Pos);
    PeriphClkInit->PLLDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLDIVR) >> RCC_DCKCFGR_PLLDIVR_Pos);
#endif /* STM32F413xx || STM32F423xx */

    /* Get the I2S APB1 clock configuration ------------------------------------*/
    PeriphClkInit->I2sApb1ClockSelection = __HAL_RCC_GET_I2S_APB1_SOURCE();

    /* Get the I2S APB2 clock configuration ------------------------------------*/
    PeriphClkInit->I2sApb2ClockSelection = __HAL_RCC_GET_I2S_APB2_SOURCE();

    /* Get the RTC Clock configuration -----------------------------------------*/
    tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
    PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));

    /* Get the FMPI2C1 clock configuration -------------------------------------*/
    PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE();

    /* Get the CLK48 clock configuration ---------------------------------------*/
    PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();

    /* Get the SDIO clock configuration ----------------------------------------*/
    PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE();

    /* Get the DFSDM1 clock configuration --------------------------------------*/
    PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE();

    /* Get the DFSDM1 Audio clock configuration --------------------------------*/
    PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE();

#if defined(STM32F413xx) || defined(STM32F423xx)
    /* Get the DFSDM2 clock configuration --------------------------------------*/
    PeriphClkInit->Dfsdm2ClockSelection = __HAL_RCC_GET_DFSDM2_SOURCE();

    /* Get the DFSDM2 Audio clock configuration --------------------------------*/
    PeriphClkInit->Dfsdm2AudioClockSelection = __HAL_RCC_GET_DFSDM2AUDIO_SOURCE();

    /* Get the LPTIM1 clock configuration --------------------------------------*/
    PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();

    /* Get the SAI1 Block Aclock configuration ---------------------------------*/
    PeriphClkInit->SaiAClockSelection = __HAL_RCC_GET_SAI_BLOCKA_SOURCE();

    /* Get the SAI1 Block B clock configuration --------------------------------*/
    PeriphClkInit->SaiBClockSelection = __HAL_RCC_GET_SAI_BLOCKB_SOURCE();
#endif /* STM32F413xx || STM32F423xx */

    /* Get the TIM Prescaler configuration -------------------------------------*/
    if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
    }
    else
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
    }
}

/**
  * @brief  Return the peripheral clock frequency for a given peripheral(I2S..)
  * @note   Return 0 if peripheral clock identifier not managed by this API
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg RCC_PERIPHCLK_I2S_APB1: I2S APB1 peripheral clock
  *            @arg RCC_PERIPHCLK_I2S_APB2: I2S APB2 peripheral clock
  * @retval Frequency in KHz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    /* This variable used to store the I2S clock frequency (value in Hz) */
    uint32_t frequency = 0U;
    /* This variable used to store the VCO Input (value in Hz) */
    uint32_t vcoinput = 0U;
    uint32_t srcclk = 0U;
    /* This variable used to store the VCO Output (value in Hz) */
    uint32_t vcooutput = 0U;
    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_I2S_APB1:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_APB1_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SAPB1CLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SAPB1CLKSOURCE_PLLI2S:
        {
            if((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SSRC) == RCC_PLLI2SCFGR_PLLI2SSRC)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(EXTERNAL_CLOCK_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
            else
            {
                /* Configure the PLLI2S division factor */
                /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
                if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
                {
                    /* Get the I2S source clock value */
                    vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
                }
                else
                {
                    /* Get the I2S source clock value */
                    vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
                }
            }
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
        case RCC_I2SAPB1CLKSOURCE_PLLR:
        {
            /* Configure the PLL division factor R */
            /* PLL_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLL_VCO Output = PLL_VCO Input * PLLN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
            /* I2S_CLK = PLL_VCO Output/PLLR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
        case RCC_I2SAPB1CLKSOURCE_PLLSRC:
        {
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                frequency = HSE_VALUE;
            }
            else
            {
                frequency = HSI_VALUE;
            }
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    case RCC_PERIPHCLK_I2S_APB2:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_APB2_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SAPB2CLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SAPB2CLKSOURCE_PLLI2S:
        {
            if((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SSRC) == RCC_PLLI2SCFGR_PLLI2SSRC)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(EXTERNAL_CLOCK_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
            else
            {
                /* Configure the PLLI2S division factor */
                /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
                if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
                {
                    /* Get the I2S source clock value */
                    vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
                }
                else
                {
                    /* Get the I2S source clock value */
                    vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
                }
            }
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
        case RCC_I2SAPB2CLKSOURCE_PLLR:
        {
            /* Configure the PLL division factor R */
            /* PLL_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLL_VCO Output = PLL_VCO Input * PLLN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
            /* I2S_CLK = PLL_VCO Output/PLLR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
        case RCC_I2SAPB2CLKSOURCE_PLLSRC:
        {
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                frequency = HSE_VALUE;
            }
            else
            {
                frequency = HSI_VALUE;
            }
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    }
    return frequency;
}
#endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */

#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx)
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
  *         RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(I2S and RTC clocks).
  *
  * @note   A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case
  *         the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup
  *        domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0U;
    uint32_t tmpreg1 = 0U;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*---------------------------- RTC configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
    {
        /* Check for RTC Parameters used to output RTCCLK */
        assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        PWR->CR |= PWR_CR_DBP;

        /* Get tick */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }
        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
        if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
        {
            /* Store the content of BDCR register before the reset of Backup Domain */
            tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();
            /* Restore the Content of BDCR register */
            RCC->BDCR = tmpreg1;

            /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
            if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
            {
                /* Get tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- TIM configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
    {
        __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- FMPI2C1 Configuration -----------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1)
    {
        /* Check the parameters */
        assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection));

        /* Configure the FMPI2C1 clock source */
        __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- LPTIM1 Configuration ------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1)
    {
        /* Check the parameters */
        assert_param(IS_RCC_LPTIM1CLKSOURCE(PeriphClkInit->Lptim1ClockSelection));

        /* Configure the LPTIM1 clock source */
        __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
    }

    /*---------------------------- I2S Configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S)
    {
        /* Check the parameters */
        assert_param(IS_RCC_I2SAPBCLKSOURCE(PeriphClkInit->I2SClockSelection));

        /* Configure the I2S clock source */
        __HAL_RCC_I2S_CONFIG(PeriphClkInit->I2SClockSelection);
    }

    return HAL_OK;
}

/**
  * @brief  Configures the RCC_OscInitStruct according to the internal
  * RCC configuration registers.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  * will be configured.
  * @retval None
  */
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tempreg;

    /* Set all possible values for the extended clock type parameter------------*/
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_FMPI2C1 | RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC;

    tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
    PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));

    if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
    }
    else
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
    }
    /* Get the FMPI2C1 clock configuration -------------------------------------*/
    PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE();

    /* Get the I2S clock configuration -----------------------------------------*/
    PeriphClkInit->I2SClockSelection = __HAL_RCC_GET_I2S_SOURCE();


}
/**
  * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
  * @note   Return 0 if peripheral clock identifier not managed by this API
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
  * @retval Frequency in KHz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    /* This variable used to store the I2S clock frequency (value in Hz) */
    uint32_t frequency = 0U;
    /* This variable used to store the VCO Input (value in Hz) */
    uint32_t vcoinput = 0U;
    uint32_t srcclk = 0U;
    /* This variable used to store the VCO Output (value in Hz) */
    uint32_t vcooutput = 0U;
    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_I2S:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SAPBCLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
        case RCC_I2SAPBCLKSOURCE_PLLR:
        {
            /* Configure the PLL division factor R */
            /* PLL_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLL_VCO Output = PLL_VCO Input * PLLN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
            /* I2S_CLK = PLL_VCO Output/PLLR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
            break;
        }
        /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
        case RCC_I2SAPBCLKSOURCE_PLLSRC:
        {
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                frequency = HSE_VALUE;
            }
            else
            {
                frequency = HSI_VALUE;
            }
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    }
    return frequency;
}
#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */

#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals
  *         clocks(I2S, SAI, LTDC RTC and TIM).
  *
  * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
  *         the RTC clock source; in this case the Backup domain will be reset in
  *         order to modify the RTC Clock source, as consequence RTC registers (including
  *         the backup registers) and RCC_BDCR register are set to their reset values.
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0U;
    uint32_t tmpreg1 = 0U;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*----------------------- SAI/I2S Configuration (PLLI2S) -------------------*/
    /*----------------------- Common configuration SAI/I2S ---------------------*/
    /* In Case of SAI or I2S Clock Configuration through PLLI2S, PLLI2SN division
       factor is common parameters for both peripherals */
    if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == RCC_PERIPHCLK_SAI_PLLI2S) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S))
    {
        /* check for Parameters */
        assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));

        /* Disable the PLLI2S */
        __HAL_RCC_PLLI2S_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /*---------------------------- I2S configuration -------------------------*/
        /* In Case of I2S Clock Configuration through PLLI2S, PLLI2SR must be added
          only for I2S configuration */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))
        {
            /* check for Parameters */
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */
            /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
            __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /*---------------------------- SAI configuration -------------------------*/
        /* In Case of SAI Clock Configuration through PLLI2S, PLLI2SQ and PLLI2S_DIVQ must
           be added only for SAI configuration */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == (RCC_PERIPHCLK_SAI_PLLI2S))
        {
            /* Check the PLLI2S division factors */
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
            assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));

            /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */
            tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
            /* Configure the PLLI2S division factors */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
            __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, tmpreg1);
            /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
            __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
        }

        /*----------------- In Case of PLLI2S is just selected  -----------------*/
        if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
        {
            /* Check for Parameters */
            assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
            assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));

            /* Configure the PLLI2S multiplication and division factors */
            __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
        }

        /* Enable the PLLI2S */
        __HAL_RCC_PLLI2S_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }
    /*--------------------------------------------------------------------------*/

    /*----------------------- SAI/LTDC Configuration (PLLSAI) ------------------*/
    /*----------------------- Common configuration SAI/LTDC --------------------*/
    /* In Case of SAI or LTDC Clock Configuration through PLLSAI, PLLSAIN division
       factor is common parameters for both peripherals */
    if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == RCC_PERIPHCLK_SAI_PLLSAI) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC))
    {
        /* Check the PLLSAI division factors */
        assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));

        /* Disable PLLSAI Clock */
        __HAL_RCC_PLLSAI_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLSAI is disabled */
        while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

        /*---------------------------- SAI configuration -------------------------*/
        /* In Case of SAI Clock Configuration through PLLSAI, PLLSAIQ and PLLSAI_DIVQ must
           be added only for SAI configuration */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == (RCC_PERIPHCLK_SAI_PLLSAI))
        {
            assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
            assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));

            /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
            tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIQ, tmpreg1);
            /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
            __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
        }

        /*---------------------------- LTDC configuration ------------------------*/
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC))
        {
            assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR));
            assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR));

            /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
            tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
            /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
            /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
            /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */
            __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, tmpreg1, PeriphClkInit->PLLSAI.PLLSAIR);
            /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */
            __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR);
        }
        /* Enable PLLSAI Clock */
        __HAL_RCC_PLLSAI_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLSAI is ready */
        while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- RTC configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
    {
        /* Check for RTC Parameters used to output RTCCLK */
        assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        PWR->CR |= PWR_CR_DBP;

        /* Get tick */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }
        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
        if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
        {
            /* Store the content of BDCR register before the reset of Backup Domain */
            tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();
            /* Restore the Content of BDCR register */
            RCC->BDCR = tmpreg1;

            /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
            if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
            {
                /* Get tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
    /*--------------------------------------------------------------------------*/

    /*---------------------------- TIM configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
    {
        __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
    }
    return HAL_OK;
}

/**
  * @brief  Configures the PeriphClkInit according to the internal
  * RCC configuration registers.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         will be configured.
  * @retval None
  */
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tempreg;

    /* Set all possible values for the extended clock type parameter------------*/
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_SAI_PLLSAI | RCC_PERIPHCLK_SAI_PLLI2S | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC;

    /* Get the PLLI2S Clock configuration -----------------------------------------------*/
    PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
    PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
    PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
    /* Get the PLLSAI Clock configuration -----------------------------------------------*/
    PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos);
    PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
    PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
    /* Get the PLLSAI/PLLI2S division factors -----------------------------------------------*/
    PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos);
    PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos);
    PeriphClkInit->PLLSAIDivR = (uint32_t)(RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVR);
    /* Get the RTC Clock configuration -----------------------------------------------*/
    tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
    PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));

    if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
    }
    else
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
    }
}

/**
  * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
  * @note   Return 0 if peripheral clock identifier not managed by this API
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
  * @retval Frequency in KHz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    /* This variable used to store the I2S clock frequency (value in Hz) */
    uint32_t frequency = 0U;
    /* This variable used to store the VCO Input (value in Hz) */
    uint32_t vcoinput = 0U;
    uint32_t srcclk = 0U;
    /* This variable used to store the VCO Output (value in Hz) */
    uint32_t vcooutput = 0U;
    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_I2S:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SCLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SCLKSOURCE_PLLI2S:
        {
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }

            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    }
    return frequency;
}
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */

#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx) ||\
    defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE)
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
  *         RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(I2S and RTC clocks).
  *
  * @note   A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case
  *         the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup
  *        domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0U;
    uint32_t tmpreg1 = 0U;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*---------------------------- I2S configuration ---------------------------*/
    if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) ||
            (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S))
    {
        /* check for Parameters */
        assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
        assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
#if defined(STM32F411xE)
        assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM));
#endif /* STM32F411xE */
        /* Disable the PLLI2S */
        __HAL_RCC_PLLI2S_DISABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }

#if defined(STM32F411xE)
        /* Configure the PLLI2S division factors */
        /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
        /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
        __HAL_RCC_PLLI2S_I2SCLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
#else
        /* Configure the PLLI2S division factors */
        /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */
        /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
        __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
#endif /* STM32F411xE */

        /* Enable the PLLI2S */
        __HAL_RCC_PLLI2S_ENABLE();
        /* Get tick */
        tickstart = HAL_GetTick();
        /* Wait till PLLI2S is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
        {
            if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
            {
                /* return in case of Timeout detected */
                return HAL_TIMEOUT;
            }
        }
    }

    /*---------------------------- RTC configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
    {
        /* Check for RTC Parameters used to output RTCCLK */
        assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        PWR->CR |= PWR_CR_DBP;

        /* Get tick */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }
        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
        if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
        {
            /* Store the content of BDCR register before the reset of Backup Domain */
            tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();
            /* Restore the Content of BDCR register */
            RCC->BDCR = tmpreg1;

            /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
            if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
            {
                /* Get tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE)
    /*---------------------------- TIM configuration ---------------------------*/
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
    {
        __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
    }
#endif /* STM32F401xC || STM32F401xE || STM32F411xE */
    return HAL_OK;
}

/**
  * @brief  Configures the RCC_OscInitStruct according to the internal
  * RCC configuration registers.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  * will be configured.
  * @retval None
  */
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tempreg;

    /* Set all possible values for the extended clock type parameter------------*/
    PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_RTC;

    /* Get the PLLI2S Clock configuration --------------------------------------*/
    PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
    PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
#if defined(STM32F411xE)
    PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM);
#endif /* STM32F411xE */
    /* Get the RTC Clock configuration -----------------------------------------*/
    tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
    PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));

#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE)
    /* Get the TIM Prescaler configuration -------------------------------------*/
    if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
    }
    else
    {
        PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
    }
#endif /* STM32F401xC || STM32F401xE || STM32F411xE */
}

/**
  * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
  * @note   Return 0 if peripheral clock identifier not managed by this API
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
  * @retval Frequency in KHz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    /* This variable used to store the I2S clock frequency (value in Hz) */
    uint32_t frequency = 0U;
    /* This variable used to store the VCO Input (value in Hz) */
    uint32_t vcoinput = 0U;
    uint32_t srcclk = 0U;
    /* This variable used to store the VCO Output (value in Hz) */
    uint32_t vcooutput = 0U;
    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_I2S:
    {
        /* Get the current I2S source */
        srcclk = __HAL_RCC_GET_I2S_SOURCE();
        switch (srcclk)
        {
        /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
        case RCC_I2SCLKSOURCE_EXT:
        {
            /* Set the I2S clock to the external clock  value */
            frequency = EXTERNAL_CLOCK_VALUE;
            break;
        }
        /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
        case RCC_I2SCLKSOURCE_PLLI2S:
        {
#if defined(STM32F411xE)
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
            }
#else
            /* Configure the PLLI2S division factor */
            /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
            if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
            else
            {
                /* Get the I2S source clock value */
                vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
            }
#endif /* STM32F411xE */
            /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
            vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
            /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
            frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
            break;
        }
        /* Clock not enabled for I2S*/
        default:
        {
            frequency = 0U;
            break;
        }
        }
        break;
    }
    }
    return frequency;
}
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE  || STM32F411xE */

#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\
    defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
/**
  * @brief  Select LSE mode
  *
  * @note   This mode is only available for STM32F410xx/STM32F411xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx  devices.
  *
  * @param  Mode specifies the LSE mode.
  *          This parameter can be one of the following values:
  *            @arg RCC_LSE_LOWPOWER_MODE:  LSE oscillator in low power mode selection
  *            @arg RCC_LSE_HIGHDRIVE_MODE: LSE oscillator in High Drive mode selection
  * @retval None
  */
void HAL_RCCEx_SelectLSEMode(uint8_t Mode)
{
    /* Check the parameters */
    assert_param(IS_RCC_LSE_MODE(Mode));
    if(Mode == RCC_LSE_HIGHDRIVE_MODE)
    {
        SET_BIT(RCC->BDCR, RCC_BDCR_LSEMOD);
    }
    else
    {
        CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEMOD);
    }
}

#endif /* STM32F410xx || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */

/** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
 *  @brief  Extended Clock management functions
 *
@verbatim
 ===============================================================================
                ##### Extended clock management functions  #####
 ===============================================================================
    [..]
    This subsection provides a set of functions allowing to control the
    activation or deactivation of PLLI2S, PLLSAI.
@endverbatim
  * @{
  */

#if defined(RCC_PLLI2S_SUPPORT)
/**
  * @brief  Enable PLLI2S.
  * @param  PLLI2SInit  pointer to an RCC_PLLI2SInitTypeDef structure that
  *         contains the configuration information for the PLLI2S
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef  *PLLI2SInit)
{
    uint32_t tickstart;

    /* Check for parameters */
    assert_param(IS_RCC_PLLI2SN_VALUE(PLLI2SInit->PLLI2SN));
    assert_param(IS_RCC_PLLI2SR_VALUE(PLLI2SInit->PLLI2SR));
#if defined(RCC_PLLI2SCFGR_PLLI2SM)
    assert_param(IS_RCC_PLLI2SM_VALUE(PLLI2SInit->PLLI2SM));
#endif /* RCC_PLLI2SCFGR_PLLI2SM */
#if defined(RCC_PLLI2SCFGR_PLLI2SP)
    assert_param(IS_RCC_PLLI2SP_VALUE(PLLI2SInit->PLLI2SP));
#endif /* RCC_PLLI2SCFGR_PLLI2SP */
#if defined(RCC_PLLI2SCFGR_PLLI2SQ)
    assert_param(IS_RCC_PLLI2SQ_VALUE(PLLI2SInit->PLLI2SQ));
#endif /* RCC_PLLI2SCFGR_PLLI2SQ */

    /* Disable the PLLI2S */
    __HAL_RCC_PLLI2S_DISABLE();

    /* Wait till PLLI2S is disabled */
    tickstart = HAL_GetTick();
    while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET)
    {
        if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
        {
            /* return in case of Timeout detected */
            return HAL_TIMEOUT;
        }
    }

    /* Configure the PLLI2S division factors */
#if defined(STM32F446xx)
    /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
    /* I2SPCLK = PLLI2S_VCO / PLLI2SP */
    /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */
    /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
    __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, \
                            PLLI2SInit->PLLI2SP, PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR);
#elif defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) ||\
      defined(STM32F413xx) || defined(STM32F423xx)
    /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/
    /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */
    /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
    __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, \
                            PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR);
#elif defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
      defined(STM32F469xx) || defined(STM32F479xx)
    /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * PLLI2SN */
    /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */
    /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
    __HAL_RCC_PLLI2S_SAICLK_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR);
#elif defined(STM32F411xE)
    /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
    /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
    __HAL_RCC_PLLI2S_I2SCLK_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR);
#else
    /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x PLLI2SN */
    /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
    __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR);
#endif /* STM32F446xx */

    /* Enable the PLLI2S */
    __HAL_RCC_PLLI2S_ENABLE();

    /* Wait till PLLI2S is ready */
    tickstart = HAL_GetTick();
    while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET)
    {
        if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
        {
            /* return in case of Timeout detected */
            return HAL_TIMEOUT;
        }
    }

    return HAL_OK;
}

/**
  * @brief  Disable PLLI2S.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_DisablePLLI2S(void)
{
    uint32_t tickstart;

    /* Disable the PLLI2S */
    __HAL_RCC_PLLI2S_DISABLE();

    /* Wait till PLLI2S is disabled */
    tickstart = HAL_GetTick();
    while(READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET)
    {
        if((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
        {
            /* return in case of Timeout detected */
            return HAL_TIMEOUT;
        }
    }

    return HAL_OK;
}

#endif /* RCC_PLLI2S_SUPPORT */

#if defined(RCC_PLLSAI_SUPPORT)
/**
  * @brief  Enable PLLSAI.
  * @param  PLLSAIInit  pointer to an RCC_PLLSAIInitTypeDef structure that
  *         contains the configuration information for the PLLSAI
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI(RCC_PLLSAIInitTypeDef  *PLLSAIInit)
{
    uint32_t tickstart;

    /* Check for parameters */
    assert_param(IS_RCC_PLLSAIN_VALUE(PLLSAIInit->PLLSAIN));
    assert_param(IS_RCC_PLLSAIQ_VALUE(PLLSAIInit->PLLSAIQ));
#if defined(RCC_PLLSAICFGR_PLLSAIM)
    assert_param(IS_RCC_PLLSAIM_VALUE(PLLSAIInit->PLLSAIM));
#endif /* RCC_PLLSAICFGR_PLLSAIM */
#if defined(RCC_PLLSAICFGR_PLLSAIP)
    assert_param(IS_RCC_PLLSAIP_VALUE(PLLSAIInit->PLLSAIP));
#endif /* RCC_PLLSAICFGR_PLLSAIP */
#if defined(RCC_PLLSAICFGR_PLLSAIR)
    assert_param(IS_RCC_PLLSAIR_VALUE(PLLSAIInit->PLLSAIR));
#endif /* RCC_PLLSAICFGR_PLLSAIR */

    /* Disable the PLLSAI */
    __HAL_RCC_PLLSAI_DISABLE();

    /* Wait till PLLSAI is disabled */
    tickstart = HAL_GetTick();
    while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
    {
        if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
        {
            /* return in case of Timeout detected */
            return HAL_TIMEOUT;
        }
    }

    /* Configure the PLLSAI division factors */
#if defined(STM32F446xx)
    /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * (PLLSAIN/PLLSAIM) */
    /* SAIPCLK = PLLSAI_VCO / PLLSAIP */
    /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */
    /* SAIRCLK = PLLSAI_VCO / PLLSAIR */
    __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIM, PLLSAIInit->PLLSAIN, \
                            PLLSAIInit->PLLSAIP, PLLSAIInit->PLLSAIQ, 0U);
#elif defined(STM32F469xx) || defined(STM32F479xx)
    /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * PLLSAIN */
    /* SAIPCLK = PLLSAI_VCO / PLLSAIP */
    /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */
    /* SAIRCLK = PLLSAI_VCO / PLLSAIR */
    __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIN, PLLSAIInit->PLLSAIP, \
                            PLLSAIInit->PLLSAIQ, PLLSAIInit->PLLSAIR);
#else
    /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) x PLLSAIN */
    /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */
    /* SAIRCLK = PLLSAI_VCO / PLLSAIR */
    __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIN, PLLSAIInit->PLLSAIQ, PLLSAIInit->PLLSAIR);
#endif /* STM32F446xx */

    /* Enable the PLLSAI */
    __HAL_RCC_PLLSAI_ENABLE();

    /* Wait till PLLSAI is ready */
    tickstart = HAL_GetTick();
    while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
    {
        if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE)
        {
            /* return in case of Timeout detected */
            return HAL_TIMEOUT;
        }
    }

    return HAL_OK;
}

/**
  * @brief  Disable PLLSAI.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI(void)
{
    uint32_t tickstart;

    /* Disable the PLLSAI */
    __HAL_RCC_PLLSAI_DISABLE();

    /* Wait till PLLSAI is disabled */
    tickstart = HAL_GetTick();
    while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
    {
        if((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
        {
            /* return in case of Timeout detected */
            return HAL_TIMEOUT;
        }
    }

    return HAL_OK;
}

#endif /* RCC_PLLSAI_SUPPORT */

/**
  * @}
  */

#if defined(STM32F446xx)
/**
  * @brief  Returns the SYSCLK frequency
  *
  * @note   This function implementation is valid only for STM32F446xx devices.
  * @note   This function add the PLL/PLLR System clock source
  *
  * @note   The system frequency computed by this function is not the real
  *         frequency in the chip. It is calculated based on the predefined
  *         constant and the selected clock source:
  * @note     If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
  * @note     If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
  * @note     If SYSCLK source is PLL or PLLR, function returns values based on HSE_VALUE(**)
  *           or HSI_VALUE(*) multiplied/divided by the PLL factors.
  * @note     (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
  *               16 MHz) but the real value may vary depending on the variations
  *               in voltage and temperature.
  * @note     (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
  *                25 MHz), user has to ensure that HSE_VALUE is same as the real
  *                frequency of the crystal used. Otherwise, this function may
  *                have wrong result.
  *
  * @note   The result of this function could be not correct when using fractional
  *         value for HSE crystal.
  *
  * @note   This function can be used by the user application to compute the
  *         baudrate for the communication peripherals or configure other parameters.
  *
  * @note   Each time SYSCLK changes, this function must be called to update the
  *         right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
  *
  *
  * @retval SYSCLK frequency
  */
uint32_t HAL_RCC_GetSysClockFreq(void)
{
    uint32_t pllm = 0U;
    uint32_t pllvco = 0U;
    uint32_t pllp = 0U;
    uint32_t pllr = 0U;
    uint32_t sysclockfreq = 0U;

    /* Get SYSCLK source -------------------------------------------------------*/
    switch (RCC->CFGR & RCC_CFGR_SWS)
    {
    case RCC_CFGR_SWS_HSI:  /* HSI used as system clock source */
    {
        sysclockfreq = HSI_VALUE;
        break;
    }
    case RCC_CFGR_SWS_HSE:  /* HSE used as system clock  source */
    {
        sysclockfreq = HSE_VALUE;
        break;
    }
    case RCC_CFGR_SWS_PLL:  /* PLL/PLLP used as system clock  source */
    {
        /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
        SYSCLK = PLL_VCO / PLLP */
        pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
        if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_HSI)
        {
            /* HSE used as PLL clock source */
            pllvco = (uint32_t) ((((uint64_t) HSE_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
        }
        else
        {
            /* HSI used as PLL clock source */
            pllvco = (uint32_t) ((((uint64_t) HSI_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
        }
        pllp = ((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> RCC_PLLCFGR_PLLP_Pos) + 1U) * 2U);

        sysclockfreq = pllvco / pllp;
        break;
    }
    case RCC_CFGR_SWS_PLLR:  /* PLL/PLLR used as system clock  source */
    {
        /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
        SYSCLK = PLL_VCO / PLLR */
        pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
        if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_HSI)
        {
            /* HSE used as PLL clock source */
            pllvco = (uint32_t) ((((uint64_t) HSE_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
        }
        else
        {
            /* HSI used as PLL clock source */
            pllvco = (uint32_t) ((((uint64_t) HSI_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
        }
        pllr = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos);

        sysclockfreq = pllvco / pllr;
        break;
    }
    default:
    {
        sysclockfreq = HSI_VALUE;
        break;
    }
    }
    return sysclockfreq;
}
#endif /* STM32F446xx */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @brief  Resets the RCC clock configuration to the default reset state.
  * @note   The default reset state of the clock configuration is given below:
  *            - HSI ON and used as system clock source
  *            - HSE, PLL, PLLI2S and PLLSAI OFF
  *            - AHB, APB1 and APB2 prescaler set to 1.
  *            - CSS, MCO1 and MCO2 OFF
  *            - All interrupts disabled
  * @note   This function doesn't modify the configuration of the
  *            - Peripheral clocks
  *            - LSI, LSE and RTC clocks
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCC_DeInit(void)
{
    uint32_t tickstart;

    /* Get Start Tick */
    tickstart = HAL_GetTick();

    /* Set HSION bit to the reset value */
    SET_BIT(RCC->CR, RCC_CR_HSION);

    /* Wait till HSI is ready */
    while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
    {
        if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
        {
            return HAL_TIMEOUT;
        }
    }

    /* Set HSITRIM[4:0] bits to the reset value */
    SET_BIT(RCC->CR, RCC_CR_HSITRIM_4);

    /* Get Start Tick */
    tickstart = HAL_GetTick();

    /* Reset CFGR register */
    CLEAR_REG(RCC->CFGR);

    /* Wait till clock switch is ready */
    while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RESET)
    {
        if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
        {
            return HAL_TIMEOUT;
        }
    }

    /* Get Start Tick */
    tickstart = HAL_GetTick();

    /* Clear HSEON, HSEBYP and CSSON bits */
    CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON);

    /* Wait till HSE is disabled */
    while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET)
    {
        if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
        {
            return HAL_TIMEOUT;
        }
    }

    /* Get Start Tick */
    tickstart = HAL_GetTick();

    /* Clear PLLON bit */
    CLEAR_BIT(RCC->CR, RCC_CR_PLLON);

    /* Wait till PLL is disabled */
    while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET)
    {
        if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
        {
            return HAL_TIMEOUT;
        }
    }

#if defined(RCC_PLLI2S_SUPPORT)
    /* Get Start Tick */
    tickstart = HAL_GetTick();

    /* Reset PLLI2SON bit */
    CLEAR_BIT(RCC->CR, RCC_CR_PLLI2SON);

    /* Wait till PLLI2S is disabled */
    while (READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET)
    {
        if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
        {
            return HAL_TIMEOUT;
        }
    }
#endif /* RCC_PLLI2S_SUPPORT */

#if defined(RCC_PLLSAI_SUPPORT)
    /* Get Start Tick */
    tickstart = HAL_GetTick();

    /* Reset PLLSAI bit */
    CLEAR_BIT(RCC->CR, RCC_CR_PLLSAION);

    /* Wait till PLLSAI is disabled */
    while (READ_BIT(RCC->CR, RCC_CR_PLLSAIRDY) != RESET)
    {
        if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
        {
            return HAL_TIMEOUT;
        }
    }
#endif /* RCC_PLLSAI_SUPPORT */

    /* Once PLL, PLLI2S and PLLSAI are OFF, reset PLLCFGR register to default value */
#if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \
    defined(STM32F423xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
    RCC->PLLCFGR = RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLR_1;
#elif defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx)
    RCC->PLLCFGR = RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLR_1 | RCC_PLLCFGR_PLLR_2 | RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_0 | RCC_PLLCFGR_PLLQ_1 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLQ_3;
#else
    RCC->PLLCFGR = RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2;
#endif /* STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F446xx || STM32F469xx || STM32F479xx */

    /* Reset PLLI2SCFGR register to default value */
#if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \
    defined(STM32F423xx) || defined(STM32F446xx)
    RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | RCC_PLLI2SCFGR_PLLI2SR_1;
#elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)
    RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1;
#elif defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx)
    RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | RCC_PLLI2SCFGR_PLLI2SR_1;
#elif defined(STM32F411xE)
    RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1;
#endif /* STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F446xx */

    /* Reset PLLSAICFGR register */
#if defined(STM32F427xx) || defined(STM32F429xx) || defined(STM32F437xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx)
    RCC->PLLSAICFGR = RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2 | RCC_PLLSAICFGR_PLLSAIR_1;
#elif defined(STM32F446xx)
    RCC->PLLSAICFGR = RCC_PLLSAICFGR_PLLSAIM_4 | RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2;
#endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F469xx || STM32F479xx */

    /* Disable all interrupts */
    CLEAR_BIT(RCC->CIR, RCC_CIR_LSIRDYIE | RCC_CIR_LSERDYIE | RCC_CIR_HSIRDYIE | RCC_CIR_HSERDYIE | RCC_CIR_PLLRDYIE);

#if defined(RCC_CIR_PLLI2SRDYIE)
    CLEAR_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYIE);
#endif /* RCC_CIR_PLLI2SRDYIE */

#if defined(RCC_CIR_PLLSAIRDYIE)
    CLEAR_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYIE);
#endif /* RCC_CIR_PLLSAIRDYIE */

    /* Clear all interrupt flags */
    SET_BIT(RCC->CIR, RCC_CIR_LSIRDYC | RCC_CIR_LSERDYC | RCC_CIR_HSIRDYC | RCC_CIR_HSERDYC | RCC_CIR_PLLRDYC | RCC_CIR_CSSC);

#if defined(RCC_CIR_PLLI2SRDYC)
    SET_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYC);
#endif /* RCC_CIR_PLLI2SRDYC */

#if defined(RCC_CIR_PLLSAIRDYC)
    SET_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYC);
#endif /* RCC_CIR_PLLSAIRDYC */

    /* Clear LSION bit */
    CLEAR_BIT(RCC->CSR, RCC_CSR_LSION);

    /* Reset all CSR flags */
    SET_BIT(RCC->CSR, RCC_CSR_RMVF);

    /* Update the SystemCoreClock global variable */
    SystemCoreClock = HSI_VALUE;

    /* Adapt Systick interrupt period */
    if(HAL_InitTick(uwTickPrio) != HAL_OK)
    {
        return HAL_ERROR;
    }
    else
    {
        return HAL_OK;
    }
}

#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\
    defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
/**
  * @brief  Initializes the RCC Oscillators according to the specified parameters in the
  *         RCC_OscInitTypeDef.
  * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
  *         contains the configuration information for the RCC Oscillators.
  * @note   The PLL is not disabled when used as system clock.
  * @note   Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
  *         supported by this API. User should request a transition to LSE Off
  *         first and then LSE On or LSE Bypass.
  * @note   Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
  *         supported by this API. User should request a transition to HSE Off
  *         first and then HSE On or HSE Bypass.
  * @note   This function add the PLL/PLLR factor management during PLL configuration this feature
  *         is only available in STM32F410xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
{
    uint32_t tickstart = 0U;

    /* Check the parameters */
    assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
    /*------------------------------- HSE Configuration ------------------------*/
    if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
    {
        /* Check the parameters */
        assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
        /* When the HSE is used as system clock or clock source for PLL in these cases HSE will not disabled */
#if defined(STM32F446xx)
        if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)                                                                     || \
                ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)) || \
                ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLLR) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
#else
        if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)                                                                     || \
                ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
#endif /* STM32F446xx */
        {
            if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
            {
                return HAL_ERROR;
            }
        }
        else
        {
            /* Set the new HSE configuration ---------------------------------------*/
            __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);

            /* Check the HSE State */
            if((RCC_OscInitStruct->HSEState) != RCC_HSE_OFF)
            {
                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till HSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
            else
            {
                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till HSE is bypassed or disabled */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET)
                {
                    if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
    }
    /*----------------------------- HSI Configuration --------------------------*/
    if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
    {
        /* Check the parameters */
        assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
        assert_param(IS_RCC_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));

        /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
#if defined(STM32F446xx)
        if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)                                                                     || \
                ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)) || \
                ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLLR) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)))
#else
        if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)                                                                     || \
                ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)))
#endif /* STM32F446xx */
        {
            /* When HSI is used as system clock it will not disabled */
            if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON))
            {
                return HAL_ERROR;
            }
            /* Otherwise, just the calibration is allowed */
            else
            {
                /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
                __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
            }
        }
        else
        {
            /* Check the HSI State */
            if((RCC_OscInitStruct->HSIState) != RCC_HSI_OFF)
            {
                /* Enable the Internal High Speed oscillator (HSI). */
                __HAL_RCC_HSI_ENABLE();

                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till HSI is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }

                /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
                __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
            }
            else
            {
                /* Disable the Internal High Speed oscillator (HSI). */
                __HAL_RCC_HSI_DISABLE();

                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till HSI is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET)
                {
                    if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
    }
    /*------------------------------ LSI Configuration -------------------------*/
    if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
    {
        /* Check the parameters */
        assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));

        /* Check the LSI State */
        if((RCC_OscInitStruct->LSIState) != RCC_LSI_OFF)
        {
            /* Enable the Internal Low Speed oscillator (LSI). */
            __HAL_RCC_LSI_ENABLE();

            /* Get Start Tick*/
            tickstart = HAL_GetTick();

            /* Wait till LSI is ready */
            while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET)
            {
                if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
                {
                    return HAL_TIMEOUT;
                }
            }
        }
        else
        {
            /* Disable the Internal Low Speed oscillator (LSI). */
            __HAL_RCC_LSI_DISABLE();

            /* Get Start Tick*/
            tickstart = HAL_GetTick();

            /* Wait till LSI is ready */
            while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET)
            {
                if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
                {
                    return HAL_TIMEOUT;
                }
            }
        }
    }
    /*------------------------------ LSE Configuration -------------------------*/
    if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
    {
        FlagStatus       pwrclkchanged = RESET;

        /* Check the parameters */
        assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));

        /* Update LSE configuration in Backup Domain control register    */
        /* Requires to enable write access to Backup Domain of necessary */
        if(__HAL_RCC_PWR_IS_CLK_DISABLED())
        {
            __HAL_RCC_PWR_CLK_ENABLE();
            pwrclkchanged = SET;
        }

        if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
        {
            /* Enable write access to Backup domain */
            SET_BIT(PWR->CR, PWR_CR_DBP);

            /* Wait for Backup domain Write protection disable */
            tickstart = HAL_GetTick();

            while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
            {
                if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
                {
                    return HAL_TIMEOUT;
                }
            }
        }

        /* Set the new LSE configuration -----------------------------------------*/
        __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
        /* Check the LSE State */
        if((RCC_OscInitStruct->LSEState) != RCC_LSE_OFF)
        {
            /* Get Start Tick*/
            tickstart = HAL_GetTick();

            /* Wait till LSE is ready */
            while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
            {
                if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                {
                    return HAL_TIMEOUT;
                }
            }
        }
        else
        {
            /* Get Start Tick*/
            tickstart = HAL_GetTick();

            /* Wait till LSE is ready */
            while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
            {
                if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                {
                    return HAL_TIMEOUT;
                }
            }
        }

        /* Restore clock configuration if changed */
        if(pwrclkchanged == SET)
        {
            __HAL_RCC_PWR_CLK_DISABLE();
        }
    }
    /*-------------------------------- PLL Configuration -----------------------*/
    /* Check the parameters */
    assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
    if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
    {
        /* Check if the PLL is used as system clock or not */
        if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
        {
            if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
            {
                /* Check the parameters */
                assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
                assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
                assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
                assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
                assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
                assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));

                /* Disable the main PLL. */
                __HAL_RCC_PLL_DISABLE();

                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till PLL is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
                {
                    if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }

                /* Configure the main PLL clock source, multiplication and division factors. */
                __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
                                     RCC_OscInitStruct->PLL.PLLM,
                                     RCC_OscInitStruct->PLL.PLLN,
                                     RCC_OscInitStruct->PLL.PLLP,
                                     RCC_OscInitStruct->PLL.PLLQ,
                                     RCC_OscInitStruct->PLL.PLLR);

                /* Enable the main PLL. */
                __HAL_RCC_PLL_ENABLE();

                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till PLL is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
            else
            {
                /* Disable the main PLL. */
                __HAL_RCC_PLL_DISABLE();

                /* Get Start Tick*/
                tickstart = HAL_GetTick();

                /* Wait till PLL is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
                {
                    if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }
        }
        else
        {
            return HAL_ERROR;
        }
    }
    return HAL_OK;
}

/**
  * @brief  Configures the RCC_OscInitStruct according to the internal
  * RCC configuration registers.
  * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that will be configured.
  *
  * @note   This function is only available in case of STM32F410xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices.
  * @note   This function add the PLL/PLLR factor management
  * @retval None
  */
void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
{
    /* Set all possible values for the Oscillator type parameter ---------------*/
    RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;

    /* Get the HSE configuration -----------------------------------------------*/
    if((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
    {
        RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
    }
    else if((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON)
    {
        RCC_OscInitStruct->HSEState = RCC_HSE_ON;
    }
    else
    {
        RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
    }

    /* Get the HSI configuration -----------------------------------------------*/
    if((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
    {
        RCC_OscInitStruct->HSIState = RCC_HSI_ON;
    }
    else
    {
        RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
    }

    RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->CR & RCC_CR_HSITRIM) >> RCC_CR_HSITRIM_Pos);

    /* Get the LSE configuration -----------------------------------------------*/
    if((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
    {
        RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
    }
    else if((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
    {
        RCC_OscInitStruct->LSEState = RCC_LSE_ON;
    }
    else
    {
        RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
    }

    /* Get the LSI configuration -----------------------------------------------*/
    if((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION)
    {
        RCC_OscInitStruct->LSIState = RCC_LSI_ON;
    }
    else
    {
        RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
    }

    /* Get the PLL configuration -----------------------------------------------*/
    if((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON)
    {
        RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
    }
    else
    {
        RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
    }
    RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
    RCC_OscInitStruct->PLL.PLLM = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
    RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
    RCC_OscInitStruct->PLL.PLLP = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) + RCC_PLLCFGR_PLLP_0) << 1U) >> RCC_PLLCFGR_PLLP_Pos);
    RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos);
    RCC_OscInitStruct->PLL.PLLR = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos);
}
#endif /* STM32F410xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */

#endif /* HAL_RCC_MODULE_ENABLED */
/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
